/**
    @file		httpd.c
    @brief 		functions associated http processing
*/

#include <stdio.h>
#include <string.h>
#include "socket.h"
#include "httpParser.h"

/*****************************************************************************
    Public types/enumerations/variables
 ****************************************************************************/
//uint8_t BUFPUB[2048];
uint8_t BUFPUB[256];

/*****************************************************************************
    Private functions
 ****************************************************************************/
static void replacetochar(uint8_t * str, uint8_t oldchar, uint8_t newchar); 	/* Replace old character with new character in the string */
static uint8_t C2D(uint8_t c); 												/* Convert a character to HEX */

/**
    @brief	convert escape characters(%XX) to ASCII character
*/
void unescape_http_url(
    char * url	/**< pointer to be converted ( escape characters )*/
) {
    int x, y;

    for (x = 0, y = 0; url[y]; ++x, ++y) {
        if ((url[x] = url[y]) == '%') {
            url[x] = C2D(url[y + 1]) * 0x10+C2D(url[y + 2]);
            y += 2;
        }
    }
    url[x] = '\0';
}


/**
    @brief	make response header such as html, gif, jpeg,etc.
*/
void make_http_response_head(
    char * buf, 	/**< pointer to response header to be made */
    char type, 	/**< response type */
    uint32_t len	/**< size of response header */
) {
    char * head;
    char tmp[10];

    /*  file type*/
    if	(type == PTYPE_HTML) {
        head = RES_HTMLHEAD_OK;
    } else if (type == PTYPE_GIF) {
        head = RES_GIFHEAD_OK;
    } else if (type == PTYPE_TEXT)	{
        head = RES_TEXTHEAD_OK;
    } else if (type == PTYPE_JPEG)	{
        head = RES_JPEGHEAD_OK;
    } else if (type == PTYPE_FLASH)	{
        head = RES_FLASHHEAD_OK;
    } else if (type == PTYPE_XML) {
        head =  RES_XMLHEAD_OK;
    } else if (type == PTYPE_CSS) {
        head = RES_CSSHEAD_OK;
    } else if (type == PTYPE_JSON)	{
        head = RES_JSONHEAD_OK;
    } else if (type == PTYPE_JS) {
        head = RES_JSHEAD_OK;
    } else if (type == PTYPE_CGI) {
        head = RES_CGIHEAD_OK;
    } else if (type == PTYPE_PNG) {
        head = RES_PNGHEAD_OK;
    } else if (type == PTYPE_ICO) {
        head = RES_ICOHEAD_OK;
    } else if (type == PTYPE_TTF) {
        head = RES_TTFHEAD_OK;
    } else if (type == PTYPE_OTF) {
        head = RES_OTFHEAD_OK;
    } else if (type == PTYPE_WOFF)	{
        head = RES_WOFFHEAD_OK;
    } else if (type == PTYPE_EOT) {
        head = RES_EOTHEAD_OK;
    } else if (type == PTYPE_SVG) {
        head = RES_SVGHEAD_OK;
    }
#ifdef _HTTPPARSER_DEBUG_
    else {
        head = NULL;
        printf("\r\n\r\n-MAKE HEAD UNKNOWN-\r\n");
    }
#else
    else {
        head = NULL;
    }
#endif

    sprintf(tmp, "%ld", len);
    strcpy(buf, head);
    strcat(buf, tmp);
    strcat(buf, "\r\n\r\n");
}


/**
    @brief	find MIME type of a file
*/
void find_http_uri_type(
    uint8_t * type, 	/**< type to be returned */
    uint8_t * buff		/**< file name */
) {
    /* Decide type according to extension*/

    char * buf;
    buf = (char *)buff;

    if	(strstr(buf, ".htm")	|| strstr(buf, ".html"))	{
        *type = PTYPE_HTML;
    } else if (strstr(buf, ".gif")) {
        *type = PTYPE_GIF;
    } else if (strstr(buf, ".text") 	|| strstr(buf, ".txt"))	{
        *type = PTYPE_TEXT;
    } else if (strstr(buf, ".jpeg") 	|| strstr(buf, ".jpg"))	{
        *type = PTYPE_JPEG;
    } else if (strstr(buf, ".swf")) {
        *type = PTYPE_FLASH;
    } else if (strstr(buf, ".cgi") 	|| strstr(buf, ".CGI"))	{
        *type = PTYPE_CGI;
    } else if (strstr(buf, ".json") 	|| strstr(buf, ".JSON"))	{
        *type = PTYPE_JSON;
    } else if (strstr(buf, ".js") 	|| strstr(buf, ".JS"))	{
        *type = PTYPE_JS;
    } else if (strstr(buf, ".CGI") 	|| strstr(buf, ".cgi"))	{
        *type = PTYPE_CGI;
    } else if (strstr(buf, ".xml") 	|| strstr(buf, ".XML"))	{
        *type = PTYPE_XML;
    } else if (strstr(buf, ".css") 	|| strstr(buf, ".CSS"))	{
        *type = PTYPE_CSS;
    } else if (strstr(buf, ".png") 	|| strstr(buf, ".PNG"))	{
        *type = PTYPE_PNG;
    } else if (strstr(buf, ".ico") 	|| strstr(buf, ".ICO"))	{
        *type = PTYPE_ICO;
    } else if (strstr(buf, ".ttf") 	|| strstr(buf, ".TTF"))	{
        *type = PTYPE_TTF;
    } else if (strstr(buf, ".otf") 	|| strstr(buf, ".OTF"))	{
        *type = PTYPE_OTF;
    } else if (strstr(buf, ".woff") 	|| strstr(buf, ".WOFF"))	{
        *type = PTYPE_WOFF;
    } else if (strstr(buf, ".eot") 	|| strstr(buf, ".EOT"))	{
        *type = PTYPE_EOT;
    } else if (strstr(buf, ".svg") 	|| strstr(buf, ".SVG"))	{
        *type = PTYPE_SVG;
    } else {
        *type = PTYPE_ERR;
    }
}


/**
    @brief	parse http request from a peer
*/
void parse_http_request(
    st_http_request * request, 	/**< request to be returned */
    uint8_t * buf				/**< pointer to be parsed */
) {
    char * nexttok;
    nexttok = strtok((char*)buf, " ");
    if (!nexttok) {
        request->METHOD = METHOD_ERR;
        return;
    }
    if (!strcmp(nexttok, "GET") || !strcmp(nexttok, "get")) {
        request->METHOD = METHOD_GET;
        nexttok = strtok(NULL, " ");

    } else if (!strcmp(nexttok, "HEAD") || !strcmp(nexttok, "head")) {
        request->METHOD = METHOD_HEAD;
        nexttok = strtok(NULL, " ");

    } else if (!strcmp(nexttok, "POST") || !strcmp(nexttok, "post")) {
        nexttok = strtok(NULL, "\0");
        request->METHOD = METHOD_POST;
    } else {
        request->METHOD = METHOD_ERR;
    }

    if (!nexttok) {
        request->METHOD = METHOD_ERR;
        return;
    }
    strcpy((char *)request->URI, nexttok);
}

#ifdef _OLD_
/**
    @brief	get next parameter value in the request
*/
uint8_t * get_http_param_value(
    char* uri,
    char* param_name
) {
    char tempURI[MAX_URI_SIZE];
    uint8_t * name = 0;


    if (!uri || !param_name) {
        return 0;
    }

    strcpy((char*)tempURI, uri);
    if ((name = (uint8_t *)strstr(tempURI, param_name))) {
        name += strlen(param_name) + 1; // strlen(para_name) + strlen("=")
        if ((name = (uint8_t *)strtok((char *)name, "& \r\n\t\0"))) {
            unescape_http_url((char *)name);
            replacetochar(name, '+', ' ');
        }
    }
#ifdef _HTTPPARSER_DEBUG_
    printf("  %s=%s", param_name, name);
#endif

    return name;
}
#else
/**
    @brief	get next parameter value in the request
*/
uint8_t * get_http_param_value(char* uri, char* param_name) {

    uint8_t * name = 0;
    uint8_t * ret = BUFPUB;
    uint8_t * pos2;
    uint16_t len = 0, content_len = 0;
    uint8_t tmp_buf[10] = {0x00, };

    if (!uri || !param_name) {
        return 0;
    }

    /***************/
    mid(uri, "Content-Length: ", "\r\n", (char *)tmp_buf);
    content_len = ATOI(tmp_buf, 10);
    uri = strstr(uri, "\r\n\r\n");
    uri += 4;
    uri[content_len] = 0;
    /***************/

    if ((name = (uint8_t *)strstr(uri, param_name))) {
        name += strlen(param_name) + 1;
        pos2 = (uint8_t*)strstr((char*)name, "&");
        if (!pos2) {
            pos2 = name + strlen((char*)name);
        }
        len = pos2 - name;

        if (len) {
            ret[len] = 0;
            strncpy((char*)ret, (char*)name, len);
            unescape_http_url((char *)ret);
            replacetochar(ret, '+', ' ');
            //ret[len] = 0;
            //ret[strlen((int8*)ret)] = 0;
            //printf("len=%d\r\n",len);
        } else {
            ret[0] = 0;
        }
    } else {
        return 0;
    }
#ifdef _HTTPPARSER_DEBUG_
    printf("  %s=%s\r\n", param_name, ret);
#endif
    return ret;
}
#endif

#ifdef _OLD_
uint8_t * get_http_uri_name(uint8_t * uri) {
    char tempURI[MAX_URI_SIZE];
    uint8_t * uri_name;

    if (!uri) {
        return 0;
    }

    strcpy(tempURI, (char *)uri);

    uri_name = (uint8_t *)strtok(tempURI, " ?");

    if (strcmp((char *)uri_name, "/")) {
        uri_name++;
    }

#ifdef _HTTPPARSER_DEBUG_
    printf("  uri_name = %s\r\n", uri_name);
#endif

    return uri_name;
}
#else

uint8_t get_http_uri_name(uint8_t * uri, uint8_t * uri_buf) {
    uint8_t * uri_ptr;
    if (!uri) {
        return 0;
    }

    strcpy((char *)uri_buf, (char *)uri);

    uri_ptr = (uint8_t *)strtok((char *)uri_buf, " ?");

    if (strcmp((char *)uri_ptr, "/")) {
        uri_ptr++;
    }
    strcpy((char *)uri_buf, (char *)uri_ptr);

#ifdef _HTTPPARSER_DEBUG_
    printf("  uri_name = %s\r\n", uri_buf);
#endif

    return 1;
}

#endif

void inet_addr_(uint8_t * addr, uint8_t *ip) {
    uint8_t i;
    uint8_t taddr[30];
    uint8_t * nexttok;
    uint8_t num;

    strcpy((char *)taddr, (char *)addr);

    nexttok = taddr;
    for (i = 0; i < 4 ; i++) {
        nexttok = (uint8_t *)strtok((char *)nexttok, ".");
        if (nexttok[0] == '0' && nexttok[1] == 'x') {
            num = ATOI(nexttok + 2, 0x10);
        } else {
            num = ATOI(nexttok, 10);
        }
        ip[i] = num;
        nexttok = NULL;
    }
}


/**
    @brief	CONVERT STRING INTO INTEGER
    @return	a integer number
*/
uint16_t ATOI(
    uint8_t * str,	/**< is a pointer to convert */
    uint8_t base	/**< is a base value (must be in the range 2 - 16) */
) {
    unsigned int num = 0;
    // debug_2013_11_25
    //        while (*str !=0)
    while ((*str != 0) && (*str != 0x20)) { // not include the space(0x020)
        num = num * base + C2D(*str++);
    }
    return num;
}

/**
    @brief Check strings and then execute callback function by each string.
    @param src The information of URI
    @param s1 The start string to be researched
    @param s2 The end string to be researched
    @param sub The string between s1 and s2
    @return The length value atfer working
*/
void mid(char* src, char* s1, char* s2, char* sub) {
    char* sub1;
    char* sub2;
    uint16_t n;

    sub1 = strstr((char*)src, (char*)s1);
    sub1 += strlen((char*)s1);
    sub2 = strstr((char*)sub1, (char*)s2);

    n = sub2 - sub1;
    strncpy((char*)sub, (char*)sub1, n);
    sub[n] = '\0';
}

////////////////////////////////////////////////////////////////////
// Static functions
////////////////////////////////////////////////////////////////////

/**
    @brief	replace the specified character in a string with new character
*/
static void replacetochar(
    uint8_t * str, 		/**< pointer to be replaced */
    uint8_t oldchar, 	/**< old character */
    uint8_t newchar	/**< new character */
) {
    int x;
    for (x = 0; str[x]; x++)
        if (str[x] == oldchar) {
            str[x] = newchar;
        }
}

/**
    @brief	CONVERT CHAR INTO HEX
    @return	HEX

    This function converts HEX(0-F) to a character
*/
static uint8_t C2D(
    uint8_t c	/**< is a character('0'-'F') to convert to HEX */
) {
    if (c >= '0' && c <= '9') {
        return c - '0';
    }
    if (c >= 'a' && c <= 'f') {
        return 10 + c - 'a';
    }
    if (c >= 'A' && c <= 'F') {
        return 10 + c - 'A';
    }

    return (char)c;
}



